package com.sxkf.template.service.impl;


import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxkf.template.constants.CommonConstants;
import com.sxkf.template.mapper.ProductLikeMapper;
import org.jeecg.common.exception.SxkfException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.CheckEmptyUtil;
import com.sxkf.template.entity.*;
import com.sxkf.template.mapper.CouponMapper;
import com.sxkf.template.mapper.ProductMapper;
import com.sxkf.template.service.*;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.RedisUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Transactional
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
    @Resource
    private ProductMapper productMapper;
    @Resource
    private ProductSpecService productSpecService;
    @Resource
    private StoreService storeService;
    @Resource
    private CouponMapper couponMapper;
    @Resource
    private RedisUtils redisUtils;

    @Resource
    private ProductLikeMapper productLikeMapper;


    @Override
    public void add(Product product) {
        save(product);

        List<ProductSpec> productSpec = product.getProductSpec();
        if (productSpec.isEmpty()) {
            throw new SxkfException("规格不能为空");
        }

        productSpec.forEach(item -> item.setProductId(product.getId()));

        productSpecService.saveBatch(productSpec);
    }

    @Override
    public IPage<Product> page(String productName, String sortType,Integer pageNo, Integer pageSize, String userId) {

        // 存缓存
        if (CheckEmptyUtil.isNotEmpty(productName) && CheckEmptyUtil.isNotEmpty(userId)) {
            List<String> hisSearch = redisUtils.lGet(CommonConstants.HIS_SEARCH + ":" + userId, 0, -1);
            if (hisSearch != null && !hisSearch.contains(productName)) {
                redisUtils.lSet(CommonConstants.HIS_SEARCH+":"+userId, productName);
            }
            // 搜索发现
            Double score = redisUtils.score(CommonConstants.SEARCH_FIND, productName);
            if (score != null) {
                redisUtils.incrementScore(CommonConstants.SEARCH_FIND,productName,1);
            }else {
                redisUtils.addZset(CommonConstants.SEARCH_FIND,productName,0);
            }
        }

        Page<Product> page = productMapper.selectPage(new Page<>(pageNo, pageSize), new LambdaQueryWrapper<Product>()
                .eq(Product::getState,"1")
                .like(CheckEmptyUtil.isNotEmpty(productName),Product::getName, productName)
                .orderByDesc("2".equals(sortType),Product::getSaleCount)
                .orderByAsc("3".equals(sortType),Product::getLowestPrice)
                .orderByDesc("4".equals(sortType),Product::getLowestPrice)
        );

        List<Product> records = page.getRecords();
        if (!records.isEmpty()){
            records.forEach(product -> {
                Store store = storeService.getById(product.getStoreId());
                if (store != null) {
                    product.setStore(store);

                    List<Coupon> coupons = couponMapper.selectList(new LambdaQueryWrapper<Coupon>().eq(Coupon::getStoreId, store.getId()));
                    product.setCoupons(coupons);
                }
            });
        }
        return page;
    }

    @Override
    public void edit(Product product) {
        updateById(product);
        // 更新或添加规格
        productSpecService.remove(new LambdaQueryWrapper<ProductSpec>().eq(ProductSpec::getProductId,product.getId()));


        List<ProductSpec> productSpec = product.getProductSpec();
        productSpec.forEach(item -> {
            item.setProductId(product.getId());
            item.setSpecAttribute(JSON.toJSONString(item.getSpecAttributeMap()));
        });

        productSpecService.saveBatch(productSpec);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(String productId) {
        boolean delProduct = removeById(productId);
        if (delProduct){
            boolean removeSpec = productSpecService.remove(new LambdaQueryWrapper<ProductSpec>()
                    .eq(ProductSpec::getProductId, productId));
            return removeSpec;
        }
        throw new SxkfException("删除失败");
    }

    @Override
    public IPage<Product> pageLike(Integer pageNo, Integer pageSize, String userId) {

        Page<ProductLike> likePage = productLikeMapper.selectPage(new Page<>(pageNo, pageSize), new LambdaQueryWrapper<ProductLike>()
                .eq(ProductLike::getUserId, userId));

        List<ProductLike> records = likePage.getRecords();

        List<String> productIdList = records.stream().map(ProductLike::getProductId).collect(Collectors.toList());

        List<Product> productList = list(new LambdaQueryWrapper<Product>().in(Product::getId, productIdList));

        Page<Product> page = new Page<>(pageNo, pageSize);
        BeanUtils.copyProperties(likePage,page);
        page.setRecords(productList);

        return page;
    }

    @Override
    public IPage<Product> typePage(Integer pageNo, Integer pageSize, Double longitude, Double latitude, String cateId, String storeType, String searchType) {

        if (CheckEmptyUtil.isNotEmpty(searchType) && searchType.equals("1") && (CheckEmptyUtil.isEmpty(longitude) || CheckEmptyUtil.isEmpty(latitude))) {
            throw new SxkfException("查找附近店铺必须有经纬度");
        }
        // 这里需要Product表 和 store 联查。
        Page<Product> page = new Page<>(pageNo, pageSize);

        long count = productMapper.typePageCount(longitude,latitude,cateId,storeType,searchType);
        Integer offset = (pageNo - 1) * pageSize;
        List<Product> records = productMapper.typePage(offset,pageSize,longitude,latitude,cateId,storeType,searchType);

        page.setTotal(count);
        long pages = count / pageSize;
        page.setPages(count % pageSize == 0 ? pages : pages + 1);
        page.setRecords(records);

        return page;
    }

    @Override
    public Page<Product> specialSale(Page<Product> page, BigDecimal price, String type) {
        Page<Product> pageRes = baseMapper.specialSale(page,price,type);
        return pageRes;
    }
}
